#![no_std]
#![no_main]
extern crate alloc;

use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::string::ToString;
use alloc::vec::Vec;
use core::cell::RefCell;
use core::fmt::Debug;
use core::sync::atomic::{AtomicBool, Ordering};
use critical_section::Mutex;
use display_interface_spi::SPIInterfaceNoCS;
use embassy_executor::Spawner;
use embassy_time::Timer;
use embedded_graphics::mono_font::iso_8859_7::FONT_5X8;
use embedded_graphics::mono_font::MonoTextStyle;
use embedded_graphics::text::Text;
use embedded_graphics_core::Drawable;
use embedded_graphics_core::pixelcolor::{BinaryColor, Rgb565};
use embedded_graphics_core::prelude::{DrawTarget, ImageDrawable, Point};
use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayMs;
use esp_hal::clock::{CpuClock, RadioClockController};
use esp_hal::delay::Delay;
use esp_hal::{handler, main, ram, spi, Blocking};
use esp_hal::gpio::{Event, Input, InputConfig, Io, Level, Output, OutputConfig, Pull};
use esp_hal::i2c::master::I2c;
use esp_hal::peripherals::Peripherals;
use esp_hal::rtc_cntl::Rtc;
use esp_hal::spi::master::Config;
use esp_hal::spi::master::Spi;
use esp_hal::time::{Duration, Instant, Rate};
use esp_hal::timer::systimer::SystemTimer;
use esp_hal::timer::timg::TimerGroup;
use esp_println::logger::{init_logger, init_logger_from_env};
use esp_println::println;
use log::{error, info, warn, LevelFilter};
use mipidsi::Display;
use slint::platform::{Platform, WindowAdapter};
use slint::platform::software_renderer::{LineBufferProvider, MinimalSoftwareWindow, Rgb565Pixel};
use slint::{invoke_from_event_loop, ModelRc, PhysicalSize, PlatformError, Rgb8Pixel, Rgba8Pixel, SharedPixelBuffer, TimerMode, Weak};
use ssd1306::{I2CDisplayInterface, Ssd1306};
use ssd1306::mode::BufferedGraphicsMode;
use ssd1306::prelude::*;

slint::include_modules!();

#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
    loop {
        error!("panic:{}",info);
    }
}


// static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();

#[esp_hal_embassy::main]
async fn main(spawner: Spawner) {
    // generator version: 0.3.1
    // init_logger_from_env();
    init_logger(LevelFilter::Debug);
    esp_alloc::heap_allocator!(size: 100 * 1024);
    info!("分配内存完成");

    let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
    let peripherals =esp_hal::init(config);

    // 配置异步
    let timer0 = SystemTimer::new(peripherals.SYSTIMER);
    esp_hal_embassy::init(timer0.alarm0);


    let i2c = esp_hal::i2c::master::I2c::new(peripherals.I2C0, esp_hal::i2c::master::Config::default()
        .with_frequency(Rate::from_khz(400)))
        .unwrap()
        .with_sda(peripherals.GPIO8)
        .with_scl(peripherals.GPIO9);

    let display = Ssd1306::new(
        I2CDisplayInterface::new(i2c),
        DisplaySize128x64,
        DisplayRotation::Rotate0).into_buffered_graphics_mode();


    info!("开启异步任务");
    spawner.spawn(ui_run(display,spawner)).ok();


    let mut io = Io::new(peripherals.IO_MUX);
    io.set_interrupt_handler(handle);
    // Pull::Up  按钮未按下，高电平，稳定   按钮按下，低电平，稳定
    let mut button = Input::new(peripherals.GPIO5,InputConfig::default().with_pull(Pull::Up));
    critical_section::with(|cs| {
        button.listen(Event::FallingEdge);
        BUTTON.borrow_ref_mut(cs).replace(button)
    });

    // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0-beta.0/examples/src/bin
}

static BUTTON: Mutex<RefCell<Option<Input>>> = Mutex::new(RefCell::new(None));
// 设置按钮按下标志位
static BUTTON_PRESSED:AtomicBool = AtomicBool::new(false);

#[handler]
#[ram]
fn handle(){
    let mut delay = Delay::new();
    delay.delay_millis(100);

    // println!("GPIO Interrupt");
    // 进入一个临界区（禁止中断），确保在多线程或中断上下文中访问共享资源的安全性
    if critical_section::with(|cs| {
        BUTTON
            .borrow_ref_mut(cs)
            .as_mut()
            .unwrap()
            .is_interrupt_set()
    }) {
        // println!("点击了按钮");

    } /*else {
        println!("Button was not the source of the interrupt");
    }*/

    // 清理中断
    critical_section::with(|cs| {
        BUTTON
            .borrow_ref_mut(cs)
            .as_mut()
            .unwrap()
            .clear_interrupt()
    });
    // 设置标志，表示按钮被按下
    BUTTON_PRESSED.store(true,Ordering::Relaxed);
}

#[embassy_executor::task]
async fn ui_run(mut display: SSD,spawner: Spawner){
    // 创建平台实例
    let window = slint::platform::software_renderer::MinimalSoftwareWindow::new(
        slint::platform::software_renderer::RepaintBufferType::ReusedBuffer,
    );
    window.set_size(PhysicalSize::new(128,64));
    let platform = EspPlatform::new(window.clone());
    slint::platform::set_platform(Box::new(platform)).unwrap();

    // 创建ui
    let ui = MainView::new().unwrap();
    ui.window().set_size(PhysicalSize::new(128,64));

    let ui_weak = ui.as_weak();
    spawner.spawn(ui_task(ui_weak)).ok();

    info!("进入了loop run");
    // 初始化显示
    display.init().unwrap();
    display.clear(BinaryColor::Off).unwrap();
    display.flush().unwrap();
    info!("清理屏幕 on");

    // 创建行缓冲区
    let display_width = 128; // 根据实际显示宽度设置
    let mut the_frame_buffer = [Rgb565Pixel(0); 128 * 64]; // 128x64
    loop {
        // 更新UI状态
        slint::platform::update_timers_and_animations();
        // info!("window has activie {}",window.has_active_animations());
        // 渲染UI
        window.draw_if_needed(|renderer| {
            // display.clear(BinaryColor::Off).unwrap();
            /*info!("进入渲染回调");*/
            // renderer.render_by_line(line_buffer);
            renderer.render_by_line(FrameBuffer{ frame_buffer: &mut the_frame_buffer, stride: display_width,display:&mut display });
            // info!("buf len {}",the_frame_buffer.len());
            /*info!("退出渲染回调");*/
            display.flush().unwrap();
        });

        if !window.has_active_animations() {
            if let Some(duration) = slint::platform::duration_until_next_timer_update(){
                Timer::after_millis(duration.as_millis() as u64).await;
                continue;
            }
        }
        Timer::after_millis(100).await;
    }
}

#[embassy_executor::task]
async fn ui_task(view:Weak<MainView>,){
    info!("ui_task 已经开启");

    /*let image = SerializableImage::deserialize(include_bytes!("../../assets/cxk-gif/cxk-1.png")).unwrap();
    view.upgrade().unwrap()
        .global::<ImageResouse>()
        .set_src(slint::Image::from_rgb8(
            SharedPixelBuffer::<Rgb8Pixel>::clone_from_slice(&image.data, image.width, image.height)
        ));*/

    /*let image = tinygif::Gif::<BinaryColor>::from_slice(include_bytes!("../../assets/cxk.gif")).unwrap();
    for frame in image.frames() {
        frame.draw(&mut display).unwrap();
        display.flush().unwrap();
        Timer::after_millis((frame.delay_centis * 10) as u64).await;
    }*/

    loop {
        Timer::after_millis(100).await;

        if BUTTON_PRESSED.load(Ordering::Relaxed){
            info!("按钮按下，执行操作");

            let view = view.clone();
            let view = view.upgrade().unwrap();
            let system = view.global::<System>();
            system.invoke_next_page();

            BUTTON_PRESSED.store(false,Ordering::Relaxed);
        }

    }

}

// #[embassy_executor::task]
// async fn ui_task_show_gif(view:Weak<MainView>){
//     loop {
//         Timer::after_millis(100).await;
//
//     }
// }

// 平台实现结构体
type SSD = Ssd1306<I2CInterface<I2c<'static,Blocking>>,DisplaySize128x64,BufferedGraphicsMode<DisplaySize128x64>>;
struct EspPlatform{
    window: Rc<MinimalSoftwareWindow>,
}

impl EspPlatform {
    fn new(window:Rc<MinimalSoftwareWindow>) -> Self {
        Self {
            window
        }
    }
}


/// 实现 Platform trait
impl Platform for EspPlatform {
    fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, PlatformError> {
        info!("成功创建了window");
        Ok(self.window.clone())
    }

    fn duration_since_start(&self) -> core::time::Duration {
        // 使用定时器获取时间（需要实际硬件计时器实现）
        let time = Instant::now().duration_since_epoch().as_millis();
        // info!("time :{}",time);
        core::time::Duration::from_millis(
            time
        )
    }
}


struct FrameBuffer<'a>{ frame_buffer: &'a mut [Rgb565Pixel], stride: usize,display:&'a mut SSD }
// 基于亮度阈值实现抗锯齿的二值化转换
const LUMINANCE_THRESHOLD: u16 = 150; // 阈值范围 0-255（根据实际效果调整）
impl<'a> LineBufferProvider for FrameBuffer<'a> {
    type TargetPixel = Rgb565Pixel;
    fn process_line(
        &mut self,
        line: usize,
        range: core::ops::Range<usize>,
        render_fn: impl FnOnce(&mut [Self::TargetPixel]),
    ) {
        let line_start = line * self.stride;
        let line_pixels = &mut self.frame_buffer[line_start..line_start + 128];
        // info!("process_line {}",line);
        render_fn(&mut line_pixels[range.clone()]);
        // warn!("设置后的：{:?}",line_pixels);

        let conv = |row:&Rgb565Pixel|{
            // 分解 RGB565 像素（RGB各通道5-6-5位）
            let r = (row.0 >> 11) & 0x1F;  // 5-bit 红色 (0-31)
            let g = (row.0 >> 5) & 0x3F;  // 6-bit 绿色 (0-63)
            let b = row.0 & 0x1F;  // 5-bit 蓝色 (0-31)

            // 转换为8-bit各通道值（扩展到位宽）
            let r8 = (r << 3) | (r >> 2);  // 5bit -> 8bit: 乘以 8.2258
            let g8 = (g << 2) | (g >> 4);  // 6bit -> 8bit: 乘以 4.0476
            let b8 = (b << 3) | (b >> 2);  // 5bit -> 8bit: 同上

            // 计算亮度（ITU-R BT.601标准）
            let luminance = (r8 as f32 * 0.299 + g8 as f32 * 0.587 + b8 as f32 * 0.114) as u16;
            luminance
        };

        for (x,row) in line_pixels.iter().enumerate(){
            self.display.set_pixel(x as u32,line as u32,false);
            let luminance = conv(row);
            if luminance>LUMINANCE_THRESHOLD{
                self.display.set_pixel(x as u32, line as u32, true);
            }
        }
    }
}




pub struct SerializableImage {
    width: u32,
    height: u32,
    data: Vec<u8>,
}

impl SerializableImage {
    pub fn deserialize(data: &[u8]) -> Result<Self, &'static str> {
        if data.len() < 8 {
            return Err("Data too short to contain width and height.");
        }
        let width = u32::from_be_bytes(data[0..4].try_into().unwrap());
        let height = u32::from_be_bytes(data[4..8].try_into().unwrap());
        let image_data = &data[8..];
        Ok(Self {
            width,
            height,
            data: image_data.to_vec(),
        })
    }
}

impl Into<SharedPixelBuffer<Rgba8Pixel>> for SerializableImage {
    fn into(self) -> SharedPixelBuffer<Rgba8Pixel> {
        SharedPixelBuffer::<Rgba8Pixel>::clone_from_slice(&self.data, self.width, self.height)
    }
}